package Serializer.impl;

import Serializer.CommonSerializer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import entity.RpcRequest;
import entity.constants;

import java.io.IOException;

public class JsonSerializer implements CommonSerializer {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public byte[] serialize(Object obj) {
        try {
            return objectMapper.writeValueAsBytes(obj);
        }catch (Exception e){
            System.out.println("序列化出错");
            return null;
        }
    }

    @Override
    public Object deserialize(byte[] bytes, Class<?> clazz) {
        try{
            Object obj = objectMapper.readValue(bytes, clazz);
            if (obj instanceof RpcRequest){
                obj = handleRequest(obj);
            }
            return obj;
        }catch (Exception e){
            System.out.println("反序列化出错");
            return null;
        }
    }

    /**
     * 这里有一个需要注意的点，就是在 RpcRequest 反序列化时，由于其中有一个字段是 Object 数组，在反序列化时序列化器会根据字段类型进行反序列化，
     * 而 Object 就是一个十分模糊的类型，会出现反序列化失败的现象，这时就需要 RpcRequest
     * 中的另一个字段 ParamTypes 来获取到 Object 数组中的每个实例的实际类，辅助反序列化，这就是 handleRequest() 方法的作用
     *
     * isAssignableFrom方法的作用：父类.class.isAssignableFrom(子类.class)
     */
    private Object handleRequest(Object obj) throws JsonProcessingException {
        RpcRequest request = (RpcRequest) obj;
        for (int i = 0; i < request.getParameters().length; i++) {
            Class<?> clazz = request.getParamTypes()[i];
            if (!clazz.isAssignableFrom(request.getParameters()[i].getClass())){
                byte[] bytes = objectMapper.writeValueAsBytes(request.getParameters()[i]);
                try {
                    request.getParameters()[i] = objectMapper.readValue(bytes, clazz);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return request;
    }


    @Override
    public int getCode() {
        return constants.JSON_SERIALIZER;
    }
}
